﻿/*!	@file
	@brief 印刷

	@author Norio Nakatani
	
	@date 2006.08.14 Moca 用紙名一覧の重複削除・情報の統合
*/
/*
	Copyright (C) 1998-2001, Norio Nakatani
	Copyright (C) 2001, hor
	Copyright (C) 2002, MIK
	Copyright (C) 2003, かろと
	Copyright (C) 2018-2022, Sakura Editor Organization

	SPDX-License-Identifier: Zlib
*/

#include "StdAfx.h"
#include <stdlib.h>
#include <WinSpool.h>
#include "CPrint.h"
#include "_main/global.h"
#include "CSelectLang.h"
#include "basis/CMyString.h"
#include "String_define.h"

// 2006.08.14 Moca 用紙名一覧の重複削除・情報の統合
const PAPER_INFO CPrint::m_paperInfoArr[] = {
	// 	用紙ID, 幅
	{DMPAPER_A4,                  2100,  2970, L"A4 (210 x 297 mm)"},
	{DMPAPER_A3,                  2970,  4200, L"A3 (297 x 420 mm)"},
	{DMPAPER_A4SMALL,             2100,  2970, L"A4 small(210 x 297 mm)"},
	{DMPAPER_A5,                  1480,  2100, L"A5 (148 x 210 mm)"},
	{DMPAPER_B4,                  2500,  3540, L"B4 (250 x 354 mm)"},
	{DMPAPER_B5,                  1820,  2570, L"B5 (182 x 257 mm)"},
	{DMPAPER_QUARTO,              2150,  2750, L"Quarto(215 x 275 mm)"},
	{DMPAPER_ENV_DL,              1100,  2200, L"DL Envelope(110 x 220 mm)"},
	{DMPAPER_ENV_C5,              1620,  2290, L"C5 Envelope(162 x 229 mm)"},
	{DMPAPER_ENV_C3,              3240,  4580, L"C3 Envelope(324 x 458 mm)"},
	{DMPAPER_ENV_C4,              2290,  3240, L"C4 Envelope(229 x 324 mm)"},
	{DMPAPER_ENV_C6,              1140,  1620, L"C6 Envelope(114 x 162 mm)"},
	{DMPAPER_ENV_C65,             1140,  2290, L"C65 Envelope(114 x 229 mm)"},
	{DMPAPER_ENV_B4,              2500,  3530, L"B4 Envelope(250 x 353 mm)"},
	{DMPAPER_ENV_B5,              1760,  2500, L"B5 Envelope(176 x 250 mm)"},
	{DMPAPER_ENV_B6,              1760,  1250, L"B6 Envelope(176 x 125 mm)"},
	{DMPAPER_ENV_ITALY,           1100,  2300, L"Italy Envelope(110 x 230 mm)"},
	{DMPAPER_LETTER,              2159,  2794, L"Letter (8 1/2 x 11 inch)"},
	{DMPAPER_LEGAL,               2159,  3556, L"Legal  (8 1/2 x 14 inch)"},
	{DMPAPER_CSHEET,              4318,  5588, L"C sheet (17 x 22 inch)"},
	{DMPAPER_DSHEET,              5588,  8634, L"D sheet (22 x 34 inch)"},
	{DMPAPER_ESHEET,              8634, 11176, L"E sheet (34 x 44 inch)"},
	{DMPAPER_LETTERSMALL,         2159,  2794, L"Letter Small (8 1/2 x 11 inch)"},
	{DMPAPER_TABLOID,             2794,  4318, L"Tabloid (11 x 17 inch)"},
	{DMPAPER_LEDGER,              4318,  2794, L"Ledger  (17 x 11 inch)"},
	{DMPAPER_STATEMENT,           1397,  2159, L"Statement (5 1/2 x 8 1/2 inch)"},
	{DMPAPER_EXECUTIVE,           1841,  2667, L"Executive (7 1/4 x 10 1/2 inch)"},
	{DMPAPER_FOLIO,               2159,  3302, L"Folio (8 1/2 x 13 inch)"},
	{DMPAPER_10X14,               2540,  3556, L"10x14 inch sheet"},
	{DMPAPER_11X17,               2794,  4318, L"11x17 inch sheet"},
	{DMPAPER_NOTE,                2159,  2794, L"Note (8 1/2 x 11 inch)"},
	{DMPAPER_ENV_9,                984,  2254, L"#9 Envelope  (3 7/8 x 8 7/8 inch)"},
	{DMPAPER_ENV_10,              1047,  2413, L"#10 Envelope (4 1/8 x 9 1/2 inch)"},
	{DMPAPER_ENV_11,              1143,  2635, L"#11 Envelope (4 1/2 x 10 3/8 inch)"},
	{DMPAPER_ENV_12,              1206,  2794, L"#12 Envelope (4 3/4 x 11 inch)"},
	{DMPAPER_ENV_14,              1270,  2921, L"#14 Envelope (5 x 11 1/2 inch)"},
	{DMPAPER_ENV_MONARCH,          984,  1905, L"Monarch Envelope (3 7/8 x 7 1/2 inch)"},
	{DMPAPER_ENV_PERSONAL,         920,  1651, L"6 3/4 Envelope (3 5/8 x 6 1/2 inch)"},
	{DMPAPER_FANFOLD_US,          3778,  2794, L"US Std Fanfold (14 7/8 x 11 inch)"},
	{DMPAPER_FANFOLD_STD_GERMAN,  2159,  3048, L"German Std Fanfold   (8 1/2 x 12 inch)"},
	{DMPAPER_FANFOLD_LGL_GERMAN,  2159,  3302, L"German Legal Fanfold (8 1/2 x 13 inch)"},
};

const int CPrint::m_nPaperInfoArrNum = _countof( m_paperInfoArr );

CPrint::CPrint( void )
{
	m_hDevMode	= nullptr;
	m_hDevNames	= nullptr;
	return;
}

CPrint::~CPrint( void )
{
	// メモリ割り当て済みならば、解放する
	// 2003.05.18 かろと
	if ( m_hDevMode != nullptr ) {
		::GlobalFree( m_hDevMode );
	}
	if ( m_hDevNames != nullptr ) {
		::GlobalFree( m_hDevNames );
	}
	m_hDevMode	= nullptr;
	m_hDevNames	= nullptr;
	return;
}

/*! @brief プリンターダイアログを表示して、プリンターを選択する
** 
** @param pPD			[i/o]	プリンターダイアログ構造体
** @param pMYDEVMODE 	[i/o] 	印刷設定

	@author かろと
	@date 2003.
*/
BOOL CPrint::PrintDlg( PRINTDLG *pPD, MYDEVMODE *pMYDEVMODE )
{
	DEVMODE*	pDEVMODE;
	DEVNAMES*	pDEVNAMES;		/* プリンター設定 DEVNAMES用*/

	// デフォルトプリンターが選択されていなければ、選択する
	if ( m_hDevMode == nullptr ) {
		if ( !GetDefaultPrinter( pMYDEVMODE ) ) {
			return FALSE;
		}
	}

	//
	//  現在のプリンター設定の必要部分を変更
	//
	pDEVMODE = (DEVMODE*)::GlobalLock( m_hDevMode );
	pDEVMODE->dmOrientation			= pMYDEVMODE->dmOrientation;
	pDEVMODE->dmPaperSize			= pMYDEVMODE->dmPaperSize;
	pDEVMODE->dmPaperLength			= pMYDEVMODE->dmPaperLength;
	pDEVMODE->dmPaperWidth			= pMYDEVMODE->dmPaperWidth;
	// PrintDlg()でReAllocされる事を考えて、呼び出す前にUnlock
	::GlobalUnlock( m_hDevMode );

	/* プリンターダイアログを表示して、プリンターを選択 */
	pPD->lStructSize = sizeof(*pPD);
	pPD->hDevMode = m_hDevMode;
	pPD->hDevNames = m_hDevNames;
	if( !::PrintDlg( pPD ) ){
		// プリンターを変更しなかった
		return FALSE;
	}

	m_hDevMode = pPD->hDevMode;
	m_hDevNames = pPD->hDevNames;

	pDEVMODE = (DEVMODE*)::GlobalLock( m_hDevMode );
	pDEVNAMES = (DEVNAMES*)::GlobalLock( m_hDevNames );

	// プリンタードライバー名
	wcscpy_s(
		pMYDEVMODE->m_szPrinterDriverName,
		_countof(pMYDEVMODE->m_szPrinterDriverName),
		(const WCHAR*)pDEVNAMES + pDEVNAMES->wDriverOffset
	);
	// プリンターデバイス名
	wcscpy_s(
		pMYDEVMODE->m_szPrinterDeviceName,
		_countof(pMYDEVMODE->m_szPrinterDeviceName),
		(const WCHAR*)pDEVNAMES + pDEVNAMES->wDeviceOffset
	);
	// プリンターポート名
	wcscpy_s(
		pMYDEVMODE->m_szPrinterOutputName,
		_countof(pMYDEVMODE->m_szPrinterOutputName),
		(const WCHAR*)pDEVNAMES + pDEVNAMES->wOutputOffset
	);

	// プリンターから得られた、dmFieldsは変更しない
	// プリンターがサポートしないbitをセットすると、プリンタードライバーによっては、不安定な動きをする場合がある
	// pMYDEVMODEは、コピーしたいbitで１のものだけセットする
	// →プリンターから得られた dmFieldsが1でないLength,Width情報に、間違った長さが入っているプリンタードライバーでは、
	//   縦・横が正しく印刷されない不具合となっていた(2003.07.03 かろと)
	pMYDEVMODE->dmFields = pDEVMODE->dmFields & (DM_ORIENTATION | DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH);
	pMYDEVMODE->dmOrientation		= pDEVMODE->dmOrientation;
	pMYDEVMODE->dmPaperSize			= pDEVMODE->dmPaperSize;
	pMYDEVMODE->dmPaperLength		= pDEVMODE->dmPaperLength;
	pMYDEVMODE->dmPaperWidth		= pDEVMODE->dmPaperWidth;

	DEBUG_TRACE( L" (入力/出力) デバイス ドライバー=[%s]\n", (WCHAR*)pDEVNAMES + pDEVNAMES->wDriverOffset );
	DEBUG_TRACE( L" (入力/出力) デバイス名=[%s]\n",        (WCHAR*)pDEVNAMES + pDEVNAMES->wDeviceOffset );
	DEBUG_TRACE( L"物理出力メディア (出力ポート) =[%s]\n", (WCHAR*)pDEVNAMES + pDEVNAMES->wOutputOffset );
	DEBUG_TRACE( L"デフォルトのプリンターか=[%d]\n",          pDEVNAMES->wDefault );

	::GlobalUnlock( m_hDevMode );
	::GlobalUnlock( m_hDevNames );
	return TRUE;
}

/*! @brief デフォルトのプリンターを取得し、MYDEVMODE に設定 
** 
** @param pMYDEVMODE 	[out] 	印刷設定
*/
BOOL CPrint::GetDefaultPrinter( MYDEVMODE* pMYDEVMODE )
{
	PRINTDLG	pd;
	DEVMODE*	pDEVMODE;
	DEVNAMES*	pDEVNAMES;		/* プリンター設定 DEVNAMES用*/

	// 2009.08.08 印刷で用紙サイズ、横指定が効かない問題対応 syat
	//// すでに DEVMODEを取得済みなら、何もしない
	//if (m_hDevMode != NULL) {
	//	return TRUE;
	//}

	// DEVMODEを取得済みでない場合、取得する
	if( m_hDevMode == nullptr ){
		//
		// PRINTDLG構造体を初期化する（ダイアログは表示しないように）
		// PrintDlg()でデフォルトプリンターのデバイス名などを取得する
		//
		memset_raw ( &pd, 0, sizeof(pd) );
		pd.lStructSize	= sizeof(pd);
		pd.Flags		= PD_RETURNDEFAULT;
		if( !::PrintDlg( &pd ) ){
			pMYDEVMODE->m_bPrinterNotFound = TRUE;	/* プリンターがなかったフラグ */
			return FALSE;
		}
		pMYDEVMODE->m_bPrinterNotFound = FALSE;	/* プリンターがなかったフラグ */

		/* 初期化 */
		memset_raw( pMYDEVMODE, 0, sizeof(*pMYDEVMODE) );
		m_hDevMode = pd.hDevMode;
		m_hDevNames = pd.hDevNames;
	}

	// MYDEVMODEへのコピー
	pDEVMODE = (DEVMODE*)::GlobalLock( m_hDevMode );
	pDEVNAMES = (DEVNAMES*)::GlobalLock( m_hDevNames );

	// プリンタードライバー名
	wcscpy_s(
		pMYDEVMODE->m_szPrinterDriverName,
		_countof(pMYDEVMODE->m_szPrinterDriverName),
		(const WCHAR*)pDEVNAMES + pDEVNAMES->wDriverOffset
	);
	// プリンターデバイス名
	wcscpy_s(
		pMYDEVMODE->m_szPrinterDeviceName,
		_countof(pMYDEVMODE->m_szPrinterDeviceName),
		(const WCHAR*)pDEVNAMES + pDEVNAMES->wDeviceOffset
	);
	// プリンターポート名
	wcscpy_s(
		pMYDEVMODE->m_szPrinterOutputName,
		_countof(pMYDEVMODE->m_szPrinterOutputName),
		(const WCHAR*)pDEVNAMES + pDEVNAMES->wOutputOffset
	);

	// プリンターから得られた、dmFieldsは変更しない
	// プリンターがサポートしないbitをセットすると、プリンタードライバーによっては、不安定な動きをする場合がある
	// pMYDEVMODEは、コピーしたいbitで１のものだけコピーする
	// →プリンターから得られた dmFieldsが1でないLength,Width情報に、間違った長さが入っているプリンタードライバーでは、
	//   縦・横が正しく印刷されない不具合となっていた(2003.07.03 かろと)
	pMYDEVMODE->dmFields = pDEVMODE->dmFields & (DM_ORIENTATION | DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH);
	pMYDEVMODE->dmOrientation		= pDEVMODE->dmOrientation;
	pMYDEVMODE->dmPaperSize			= pDEVMODE->dmPaperSize;
	pMYDEVMODE->dmPaperLength		= pDEVMODE->dmPaperLength;
	pMYDEVMODE->dmPaperWidth		= pDEVMODE->dmPaperWidth;

	DEBUG_TRACE( L" (入力/出力) デバイス ドライバー=[%s]\n", (WCHAR*)pDEVNAMES + pDEVNAMES->wDriverOffset );
	DEBUG_TRACE( L" (入力/出力) デバイス名=[%s]\n",        (WCHAR*)pDEVNAMES + pDEVNAMES->wDeviceOffset );
	DEBUG_TRACE( L"物理出力メディア (出力ポート) =[%s]\n", (WCHAR*)pDEVNAMES + pDEVNAMES->wOutputOffset );
	DEBUG_TRACE( L"デフォルトのプリンターか=[%d]\n",          pDEVNAMES->wDefault );

	::GlobalUnlock( m_hDevMode );
	::GlobalUnlock( m_hDevNames );
	return TRUE;
}

/*! 
** @brief プリンターをオープンし、hDCを作成する
*/
HDC CPrint::CreateDC(
	MYDEVMODE*	pMYDEVMODE,
	WCHAR*		pszErrMsg		/* エラーメッセージ格納場所 */
)
{
	HDC			hdc = nullptr;
	HANDLE		hPrinter = nullptr;
	DEVMODE*	pDEVMODE;

	// プリンターが選択されていなければ、NULLを返す
	if ( m_hDevMode == nullptr ) {
		return nullptr;
	}

	//
	// OpenPrinter()で、デバイス名でプリンターハンドルを取得
	//
	if( !::OpenPrinter(
		pMYDEVMODE->m_szPrinterDeviceName,		/* プリンターデバイス名 */
		&hPrinter,					/* プリンターハンドルのポインタ */
		nullptr
	) ){
		auto_sprintf(
			pszErrMsg,
			LS(STR_ERR_CPRINT01),
			pMYDEVMODE->m_szPrinterDeviceName	/* プリンターデバイス名 */
		);
		goto end_of_func;
	}

	pDEVMODE = (DEVMODE*)::GlobalLock( m_hDevMode );
	pDEVMODE->dmOrientation			= pMYDEVMODE->dmOrientation;
	pDEVMODE->dmPaperSize			= pMYDEVMODE->dmPaperSize;
	pDEVMODE->dmPaperLength			= pMYDEVMODE->dmPaperLength;
	pDEVMODE->dmPaperWidth			= pMYDEVMODE->dmPaperWidth;

	//
	//DocumentProperties()でアプリケーション独自のプリンター設定に変更する
	//
	::DocumentProperties(
		nullptr,
		hPrinter,
		pMYDEVMODE->m_szPrinterDeviceName	/* プリンターデバイス名 */,
		pDEVMODE,
		pDEVMODE,
		DM_OUT_BUFFER | DM_IN_BUFFER
	);
	/* 指定デバイスに対するデバイス コンテキストを作成します。 */
	hdc = ::CreateDC(
		pMYDEVMODE->m_szPrinterDriverName,	/* プリンタードライバー名 */
		pMYDEVMODE->m_szPrinterDeviceName,	/* プリンターデバイス名 */
		pMYDEVMODE->m_szPrinterOutputName,	/* プリンターポート名 */
		pDEVMODE
	);

	// pMYDEVMODEは、コピーしたいbitで１のものだけコピーする
	// →プリンターから得られた dmFieldsが1でないLength,Width情報に、間違った長さが入っているプリンタードライバーでは、
	//   縦・横が正しく印刷されない不具合となっていた(2003.07.03 かろと)
	pMYDEVMODE->dmFields = pDEVMODE->dmFields & (DM_ORIENTATION | DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH);
	pMYDEVMODE->dmOrientation		= pDEVMODE->dmOrientation;
	pMYDEVMODE->dmPaperSize			= pDEVMODE->dmPaperSize;
	pMYDEVMODE->dmPaperLength		= pDEVMODE->dmPaperLength;
	pMYDEVMODE->dmPaperWidth		= pDEVMODE->dmPaperWidth;

	::GlobalUnlock( m_hDevMode );

end_of_func:;
	if (hPrinter != nullptr) {
		::ClosePrinter( hPrinter );
	}

	return hdc;
}

/* 印刷/プレビューに必要な情報を取得 */
BOOL CPrint::GetPrintMetrics(
	MYDEVMODE*	pMYDEVMODE,
	short*		pnPaperAllWidth,	/* 用紙幅 */
	short*		pnPaperAllHeight,	/* 用紙高さ */
	short*		pnPaperWidth,		/* 用紙印刷可能幅 */
	short*		pnPaperHeight,		/* 用紙印刷可能高さ */
	short*		pnPaperOffsetLeft,	/* 用紙余白左端 */
	short*		pnPaperOffsetTop,	/* 用紙余白上端 */
	WCHAR*		pszErrMsg			/* エラーメッセージ格納場所 */
)
{
	BOOL		bRet;
	HDC			hdc;
	bRet = TRUE;

	/* 現在の設定で、用紙の幅、高さを確定し、CreateDCに渡す */
	if( !GetPaperSize( pnPaperAllWidth, pnPaperAllHeight, pMYDEVMODE ) ){
		*pnPaperAllWidth = *pnPaperWidth + 2 * (*pnPaperOffsetLeft);
		*pnPaperAllHeight = *pnPaperHeight + 2 * (*pnPaperOffsetTop);
	}

	// pMYDEVMODEを使って、hdcを取得
	if ( nullptr == (hdc = CreateDC( pMYDEVMODE, pszErrMsg )) ){
		return FALSE;
	}

	/* CreateDC実行によって得られた実際のプリンターの用紙の幅、高さを取得 */
	if( !GetPaperSize( pnPaperAllWidth, pnPaperAllHeight, pMYDEVMODE ) ){
		*pnPaperAllWidth = *pnPaperWidth + 2 * (*pnPaperOffsetLeft);
		*pnPaperAllHeight = *pnPaperHeight + 2 * (*pnPaperOffsetTop);
	}

	/* マッピング モードの設定 */
	::SetMapMode( hdc, MM_LOMETRIC );	//MM_LOMETRIC	それぞれの論理単位は 0.1 mm にマップされます。

	/* 最小左マージンと最小上マージンを取得(1mm単位) */
	POINT	po;
	if( 0 < ::Escape( hdc, GETPRINTINGOFFSET, 0, nullptr, (LPPOINT)&po ) ){
		::DPtoLP( hdc, &po, 1 );
		*pnPaperOffsetLeft = (short)abs( po.x );	/* 用紙余白左端 */
		*pnPaperOffsetTop  = (short)abs( po.y );	/* 用紙余白上端 */
	}else{
		*pnPaperOffsetLeft = 0;	/* 用紙余白左端 */
		*pnPaperOffsetTop  = 0;	/* 用紙余白上端 */
	}

	/* 用紙の印刷可能な幅、高さ */
	po.x = ::GetDeviceCaps( hdc, HORZRES );	/* 用紙印刷可能幅←物理ディスプレイの幅 (mm 単位) */
	po.y = ::GetDeviceCaps( hdc, VERTRES );	/* 用紙印刷可能高さ←物理ディスプレイの高さ (mm 単位)  */
	::DPtoLP( hdc, &po, 1 );
	*pnPaperWidth  = (short)abs( po.x );
	*pnPaperHeight = (short)abs( po.y );

	::DeleteDC( hdc );

	return bRet;
}

/* 用紙の幅、高さ */
BOOL CPrint::GetPaperSize(
	short*		pnPaperAllWidth,
	short*		pnPaperAllHeight,
	MYDEVMODE*	pDEVMODE
)
{
	short	nWork;

	if( pDEVMODE->dmFields &  DM_PAPERSIZE ){
		// 2006.08.14 Moca swich/caseテーブルを廃止して 用紙情報を統合
		const PAPER_INFO* pi = FindPaperInfo( pDEVMODE->dmPaperSize );
		if( nullptr != pi ){
			*pnPaperAllWidth = pi->m_nAllWidth;
			*pnPaperAllHeight = pi->m_nAllHeight;
		}else{
			// 2001.12.21 hor マウスでクリックしたままリスト外に出るとここにくるけど、
			//	異常ではないので FALSE を返すことにする
			return FALSE;
		}
	}
	if(pDEVMODE->dmFields & DM_PAPERLENGTH && 0 != pDEVMODE->dmPaperLength ){
		/* pDEVMODE->dmPaperLengthは1/10mm単位である */
		*pnPaperAllHeight = pDEVMODE->dmPaperLength/* * 10*/;
	} else {
		pDEVMODE->dmPaperLength = *pnPaperAllHeight;
		pDEVMODE->dmFields |= DM_PAPERLENGTH;
	}
	if(pDEVMODE->dmFields & DM_PAPERWIDTH && 0 != pDEVMODE->dmPaperWidth ){
		/* pDEVMODE->dmPaperWidthは1/10mm単位である */
		*pnPaperAllWidth = pDEVMODE->dmPaperWidth/* * 10*/;
	} else {
		pDEVMODE->dmPaperWidth = *pnPaperAllWidth;
		pDEVMODE->dmFields |= DM_PAPERWIDTH;
	}
	/* 用紙の方向 */
	if( DMORIENT_LANDSCAPE == pDEVMODE->dmOrientation ){
		nWork = *pnPaperAllWidth;
		*pnPaperAllWidth = *pnPaperAllHeight;
		*pnPaperAllHeight = nWork;
	}
	return TRUE;
}

/* 印刷 ジョブ開始 */
BOOL CPrint::PrintOpen(
	WCHAR*		pszJobName,
	MYDEVMODE*	pMYDEVMODE,
	HDC*		phdc,
	WCHAR*		pszErrMsg		/* エラーメッセージ格納場所 */
)
{
	BOOL		bRet;
	HDC			hdc;
	DOCINFO		di;
	bRet = TRUE;
	// 
	// hdcを取得
	//
	if ( nullptr == (hdc = CreateDC( pMYDEVMODE, pszErrMsg )) ){
		bRet = FALSE;
		goto end_of_func;
	}

	/* マッピング モードの設定 */
	::SetMapMode( hdc, MM_LOMETRIC );	//MM_LOMETRIC		それぞれの論理単位は、0.1 mm にマップされます。

	//
	//  印刷ジョブ開始
	//
	memset_raw( &di, 0, sizeof( di ) );
	di.cbSize = sizeof(di);
	di.lpszDocName = pszJobName;
	di.lpszOutput  = nullptr;
	di.lpszDatatype = nullptr;
	di.fwType = 0;
	if( 0 >= ::StartDoc( hdc, &di ) ){
		auto_sprintf(
			pszErrMsg,
			LS(STR_ERR_CPRINT02),
			pMYDEVMODE->m_szPrinterDeviceName	/* プリンターデバイス名 */
		);
		bRet = FALSE;
		goto end_of_func;
	}

	*phdc = hdc;

end_of_func:;

	return bRet;
}

/* 印刷 ページ開始 */
void CPrint::PrintStartPage( HDC hdc )
{
	::StartPage( hdc );
}

/* 印刷 ページ終了 */
void CPrint::PrintEndPage( HDC hdc )
{
	::EndPage( hdc );
}

/* 印刷 ジョブ終了 */
void CPrint::PrintClose( HDC hdc )
{
	::EndDoc( hdc );
	::DeleteDC( hdc );
}

/* 用紙の名前を取得 */
WCHAR* CPrint::GetPaperName( int nPaperSize, WCHAR* pszPaperName )
{
	// 2006.08.14 Moca 用紙情報の統合
	const PAPER_INFO* paperInfo = FindPaperInfo( nPaperSize );
	if( nullptr != paperInfo ){
		wcscpy( pszPaperName, paperInfo->m_pszName );
	}else{
		wcscpy( pszPaperName, LS(STR_ERR_CPRINT03) );
	}
	return pszPaperName;
}

/*!
	用紙情報の取得
	@date 2006.08.14 Moca 新規作成 用紙情報の統合
*/
const PAPER_INFO* CPrint::FindPaperInfo( int id )
{
	for( int i = 0; i < m_nPaperInfoArrNum; ++i ){
		if( m_paperInfoArr[i].m_nId == id ){
			return &(m_paperInfoArr[i]);
		}
	}
	return nullptr;
}

/*!	@brief PRINTSETTINGの初期化

	ここではm_mdmDevModeの プリンター設定は取得・初期化しない

	@date 2006.08.14 Moca  Initializeから名称変更。初期化単位をShareDate全てからPRINTSETTING単位に変更．
		本関数からDLLSHAREDATAへアクセスする代わりに，CShareDataからPPRINTSETTING単位で逐一渡してもらう．
*/
void CPrint::SettingInitialize( PRINTSETTING& pPrintSetting, const WCHAR* settingName )
{
	wcscpy( pPrintSetting.m_szPrintSettingName, settingName );			/* 印刷設定の名前 */
	wcscpy( pPrintSetting.m_szPrintFontFaceHan, L"ＭＳ 明朝" );		/* 印刷フォント */
	wcscpy( pPrintSetting.m_szPrintFontFaceZen, L"ＭＳ 明朝" );		/* 印刷フォント */
	pPrintSetting.m_bColorPrint = false;		// カラー印刷			// 2013/4/26 Uchi
	pPrintSetting.m_nPrintFontWidth = 12;		// 印刷フォント幅(1/10mm単位)
	pPrintSetting.m_nPrintFontHeight = pPrintSetting.m_nPrintFontWidth * 2;	/* 印刷フォント高さ(1/10mm単位単位) */
	pPrintSetting.m_nPrintDansuu = 1;			/* 段組の段数 */
	pPrintSetting.m_nPrintDanSpace = 70; 		/* 段と段の隙間(1/10mm) */
	pPrintSetting.m_bPrintWordWrap = true;		// 英文ワードラップする
	pPrintSetting.m_bPrintKinsokuHead = false;	// 行頭禁則する			//@@@ 2002.04.09 MIK
	pPrintSetting.m_bPrintKinsokuTail = false;	// 行末禁則する			//@@@ 2002.04.09 MIK
	pPrintSetting.m_bPrintKinsokuRet  = false;	// 改行文字をぶら下げる	//@@@ 2002.04.13 MIK
	pPrintSetting.m_bPrintKinsokuKuto = false;	// 2006.08.14 Moca 初期化ミス
	pPrintSetting.m_bPrintLineNumber = false;	/* 行番号を印刷する */
	pPrintSetting.m_nPrintLineSpacing = 30;	/* 印刷フォント行間 文字の高さに対する割合(%) */
	pPrintSetting.m_nPrintMarginTY = 100;		/* 印刷用紙マージン 上(1/10mm単位) */
	pPrintSetting.m_nPrintMarginBY = 200;		/* 印刷用紙マージン 下(1/10mm単位) */
	pPrintSetting.m_nPrintMarginLX = 200;		/* 印刷用紙マージン 左(1/10mm単位) */
	pPrintSetting.m_nPrintMarginRX = 100;		/* 印刷用紙マージン 右(1/10mm単位) */
	pPrintSetting.m_nPrintPaperOrientation = DMORIENT_PORTRAIT;	/* 用紙方向 DMORIENT_PORTRAIT (1) または DMORIENT_LANDSCAPE (2) */
	pPrintSetting.m_nPrintPaperSize = DMPAPER_A4;	/* 用紙サイズ */
	/* プリンター設定 DEVMODE用 */
	/* プリンター設定を取得するのはコストがかかるので、後ほど */
	//	m_cPrint.GetDefaultPrinterInfo( &(pPrintSetting.m_mdmDevMode) );
	pPrintSetting.m_bHeaderUse[0] = TRUE;
	pPrintSetting.m_bHeaderUse[1] = FALSE;
	pPrintSetting.m_bHeaderUse[2] = FALSE;
	wcscpy( pPrintSetting.m_szHeaderForm[0], L"$f" );
	pPrintSetting.m_szHeaderForm[1][0] = L'\0';
	pPrintSetting.m_szHeaderForm[2][0] = L'\0';
	pPrintSetting.m_bFooterUse[0] = TRUE;
	pPrintSetting.m_bFooterUse[1] = FALSE;
	pPrintSetting.m_bFooterUse[2] = FALSE;
	pPrintSetting.m_szFooterForm[0][0] = L'\0';
	wcscpy( pPrintSetting.m_szFooterForm[1], L"- $p -" );
	pPrintSetting.m_szFooterForm[2][0] = L'\0';
}

/*!
	印字可能桁数の計算
	@date 2013.05.10 aroka 新規作成
*/
int CPrint::CalculatePrintableColumns( PRINTSETTING *pPS, int nPaperAllWidth, int nLineNumberColumns )
{
	int nPrintablePaperWidth = nPaperAllWidth - pPS->m_nPrintMarginLX - pPS->m_nPrintMarginRX;
	if( nPrintablePaperWidth < 0 ){ return 0; }

	int nPrintSpaceWidth = ( pPS->m_nPrintDansuu - 1 ) * pPS->m_nPrintDanSpace
						 + ( pPS->m_nPrintDansuu ) * ( nLineNumberColumns * pPS->m_nPrintFontWidth );
	if( nPrintablePaperWidth < nPrintSpaceWidth ){ return 0; }

	int nEnableColumns =
		( nPrintablePaperWidth - nPrintSpaceWidth
		) / pPS->m_nPrintFontWidth / pPS->m_nPrintDansuu;	/* 印字可能桁数/ページ */
	return nEnableColumns;
}

/*!
	印字可能行数の計算
	@date 2013.05.10 aroka 新規作成
*/
int CPrint::CalculatePrintableLines( PRINTSETTING *pPS, int nPaperAllHeight )
{
	int nPrintablePaperHeight = nPaperAllHeight - pPS->m_nPrintMarginTY - pPS->m_nPrintMarginBY;
	if( nPrintablePaperHeight < 0 ){ return 0; }

	int nPrintSpaceHeight = ( pPS->m_nPrintFontHeight * pPS->m_nPrintLineSpacing / 100 );

	int nEnableLines =
		( nPrintablePaperHeight - CalcHeaderHeight( pPS )*2 - CalcFooterHeight( pPS )*2 + nPrintSpaceHeight ) /
		( pPS->m_nPrintFontHeight + nPrintSpaceHeight );	// 印字可能行数/ページ
	if( nEnableLines < 0 ){ return 0; }
	return nEnableLines;
}

/*!
	ヘッダー高さの計算(行送り分こみ)
	@date 2013.05.16 Uchi 新規作成
*/
int CPrint::CalcHeaderHeight( PRINTSETTING* pPS )
{
	if (pPS->m_szHeaderForm[0][0] == L'\0'
	 && pPS->m_szHeaderForm[1][0] == L'\0'
	 && pPS->m_szHeaderForm[2][0] == L'\0') {
		// 使ってなければ 0
		return 0;
	}

	int		nHeight;
	if (pPS->m_lfHeader.lfFaceName[0] == L'\0') {
		// フォント指定無し
		nHeight = pPS->m_nPrintFontHeight;
	}
	else {
		// フォントのサイズ計算(pt->1/10mm)
		nHeight = pPS->m_nHeaderPointSize * 254 / 720;
	}
	return nHeight * (pPS->m_nPrintLineSpacing + 100) / 100;	// 行送り計算
}

/*!
	フッター高さの計算(行送り分こみ)
	@date 2013.05.16 Uchi 新規作成
*/
int CPrint::CalcFooterHeight( PRINTSETTING* pPS )
{
	if (pPS->m_szFooterForm[0][0] == L'\0'
	 && pPS->m_szFooterForm[1][0] == L'\0'
	 && pPS->m_szFooterForm[2][0] == L'\0') {
		// 使ってなければ 0
		 return 0;
	}

	int		nHeight;
	if (pPS->m_lfFooter.lfFaceName[0] == L'\0') {
		// フォント指定無し
		nHeight = pPS->m_nPrintFontHeight;
	}
	else {
		// フォントのサイズ計算(pt->1/10mm)
		nHeight = pPS->m_nFooterPointSize * 254 / 720;
	}
	return nHeight * (pPS->m_nPrintLineSpacing + 100) / 100;	// 行送り計算
}
